var Loadclick={
	click:function(){
		ulttool.loginfo('Loadclick!');
	}
};

var ulttool={
	init:function(){
//		Components.utils.import("resource://gre/modules/FileUtils.jsm");
		ulttool.Cc = Components.classes;
		ulttool.Ci = Components.interfaces;
		ulttool.console = ulttool.Cc["@mozilla.org/consoleservice;1"].getService(ulttool.Ci.nsIConsoleService);
		ulttool.scriptloader= ulttool.Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(ulttool.Ci.mozIJSSubScriptLoader);
		ulttool.ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
		ulttool.ResProt = ulttool.ioService.getProtocolHandler("resource").QueryInterface(ulttool.Ci.nsIResProtocolHandler);
		ulttool.ResProt.setSubstitution('antiyouku', ulttool.ioService.newURI("chrome://antiyouku/content/player/", null, null));
	},
	loginfo:function(infostr){
		ulttool.console.logStringMessage(infostr);
	},
	loadsubScript:function(scriptpath){
		ulttool.scriptloader.loadSubScript("chrome://antiyouku/content/ChannelReplacement.js");
		ulttool.scriptloader.loadSubScript("chrome://antiyouku/content/UltIo.js");
	},
	CCIN:function (cName, ifaceName) {
    	return ulttool.Cc[cName].createInstance(ulttool.Ci[ifaceName]);
	},
	loadfile:function(name,charset){
		var res;
//		var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		var file = Components.classes["@mozilla.org/file/directory_service;1"].
           getService(Components.interfaces.nsIProperties).
           get("ProfD", Components.interfaces.nsIFile);
//		file.initWithPath(path);
		file.append('antiyouku');
		file.append(name);
        var is = ulttool.Cc["@mozilla.org/network/file-input-stream;1"].createInstance(ulttool.Ci.nsIFileInputStream);
        is.init(file, 0x01, 256, null);
        var sis = ulttool.Cc["@mozilla.org/scriptableinputstream;1"].createInstance(ulttool.Ci.nsIScriptableInputStream);
        sis.init(is);

        res = sis.read(sis.available());
        is.close();
        
        if (charset !== null) { // use "null" if you want uncoverted data...
            var unicodeConverter = ulttool.Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(ulttool.Ci.nsIScriptableUnicodeConverter);
            try {
                unicodeConverter.charset = charset || "UTF-8";
            } catch(ex) {
                unicodeConverter.charset = "UTF-8";
            }
            res = unicodeConverter.ConvertToUnicode(res);
        }
        return res;
	},
	loadbytefile:function (name){
		var res;
//		var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		var file = Components.classes["@mozilla.org/file/directory_service;1"].
           getService(Components.interfaces.nsIProperties).
           get("ProfD", Components.interfaces.nsIFile);
//		file.initWithPath(path);
		file.append('antiyouku');
		file.append(name);
        var is = ulttool.Cc["@mozilla.org/network/file-input-stream;1"].createInstance(ulttool.Ci.nsIFileInputStream);
        is.init(file, -1, -1, false);
        var bstream = Components.classes["@mozilla.org/binaryinputstream;1"].
              createInstance(Components.interfaces.nsIBinaryInputStream);
		bstream.setInputStream(is);

        res = bstream.readBytes(bstream.available());
        is.close();
        return res;
	},
	max:function(a,b){
		if(a>=b) return a ;
		return b;
	}
};

ulttool.init();

var httpRequestObserver =
{ 
  observe: function(subject, topic, data) {
    if (topic == "http-on-modify-request") {

        var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);     
        var requestURL = subject.URI.spec;

        if (requestURL.search(/http:\/\/static\.youku\.com(\/v[\d\.]*)?\/v\/swf\/player.*\.swf/) >= 0)  {
        	filecontent = ulttool.loadbytefile('player.swf');
        	httpChannel.setResponseHeader("Content-Length",filecontent.length,true);
        	ulttool.loginfo('http-on-modify-request Content-Length:'+httpChannel.getResponseHeader("Content-Length"));
        }
    }
    
    if (topic == "http-on-examine-response") {
		var newListener = new TracingListener();
        var traceableChannel = subject.QueryInterface(Components.interfaces.nsITraceableChannel);
        newListener.originalListener = traceableChannel.setNewListener(newListener);  
        var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel); 
//        ulttool.loginfo('httpChannel.getResponseHeader("Content-Length"):'+httpChannel.getResponseHeader("Content-Length"));
		try{
			requestURL = subject.URI.spec;
			if (requestURL.search(/http:\/\/static\.youku\.com(\/v[\d\.]*)?\/v\/swf\/player.*\.swf/) >= 0){
				newListener.reqlength = parseInt(httpChannel.getResponseHeader("Content-Length"));
				filecontent = ulttool.loadbytefile(filename);
				
//				httpChannel.setResponseHeader("Content-Length",filecontent.length,true);
			}
        }catch(err){
        }
    }

  },
  
  isToBeReplaced: function(requestURL) {
	
	if(requestURL.search(/crossdomain\.xml/ig)>=0){
		ulttool.loginfo('-------requestURL:'+requestURL);
		if (requestURL=='http://v.youku.com/crossdomain.xml'){
			return false;
		}
		return false;
	}else{
		return false;
	}
	
  },

  get observerService() {
    return Components.classes["@mozilla.org/observer-service;1"]
                     .getService(Components.interfaces.nsIObserverService);
  },

  register: function() {
//		this.observerService.addObserver(this, "http-on-modify-request", false);
		this.observerService.addObserver(this, "http-on-examine-response", false);
  },
  
  unregister: function() {
//		this.observerService.removeObserver(this, "http-on-modify-request");
		this.observerService.removeObserver(this, "http-on-examine-respons");
  }
};

httpRequestObserver.register();


function TracingListener() {
	this.originalListener = null;
	this.offset = 0;
}

TracingListener.prototype =
{
	replacement:function (request, context, inputStream, offset, count,filename){
		ulttool.loginfo('TracingListener: request.name is:'+request.name);
		ulttool.loginfo('this.reqlength:'+this.reqlength);
//	    ulttool.loginfo('this.offset is:'+this.offset);
	    ulttool.loginfo('getdata from:'+offset+'<-->to:'+(offset+count));
	    
		filecontent = ulttool.loadbytefile(filename);
		
		var binaryInputStream = ulttool.CCIN("@mozilla.org/binaryinputstream;1","nsIBinaryInputStream");
		var storageStream = ulttool.CCIN("@mozilla.org/storagestream;1", "nsIStorageStream");
    	var binaryOutputStream = ulttool.CCIN("@mozilla.org/binaryoutputstream;1","nsIBinaryOutputStream");
            
        binaryInputStream.setInputStream(inputStream);
//        ulttool.loginfo(ulttool.max(filecontent.length,this.reqlength));
    	storageStream.init(8192,filecontent.length, null);
    	binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
    	
    	var data = binaryInputStream.readBytes(count);
		binaryOutputStream.writeBytes(filecontent, filecontent.length);
		
		if(count+offset<this.reqlength){
//			ulttool.loginfo('senddata from:'+this.offset+'<-->to:'+(this.offset+1000));
			this.count = (count+offset)/this.reqlength * filecontent.length;
			this.count = parseInt(this.count.toString());
			if (this.count == filecontent.length){
				this.count = this.count-this.offset-1;
			}else{
				this.count = this.count-this.offset;
			}
			ulttool.loginfo('senddata from:'+this.offset+'<-->to:'+(this.offset+this.count));
			this.originalListener.onDataAvailable(request, context,storageStream.newInputStream(this.offset),this.offset,this.count);
			this.offset+=this.count;
		}else{
//			var filllen = 0;
//			if (filecontent.length > this.reqlength){
//				this.count = filecontent.length - this.offset;
//			}else{
//				this.count = this.reqlength - this.offset;
//				filllen = this.reqlength - filecontent.length;
//			}
//			while(filllen>0){
//				filllen--;
//				binaryOutputStream.writeBytes(0x00,1);
//			}
			this.count = filecontent.length - this.offset;
			ulttool.loginfo('senddata from:'+this.offset+'<-->to:'+(this.offset+this.count));
			this.originalListener.onDataAvailable(request, context,storageStream.newInputStream(this.offset),this.offset,this.count);
		}
	},
    onDataAvailable: function(request, context, inputStream, offset, count) {

//    	if (request.name=='http://v.youku.com/crossdomain.xml'){
//	    	this.replacement(request, context, inputStream, offset, count,'crossdomain.xml')
//    		return;
//	    }
	    
	    if(request.name.search(/http:\/\/static\.youku\.com(\/v[\d\.]*)?\/v\/swf\/player.*\.swf/) >= 0){
	    	this.replacement(request, context, inputStream, offset, count,'player.swf')
    		return;
	    }
	    
	    if(request.name.search(/http:\/\/player\.ku6cdn\.com\/default\/common\/player\/\d*\/player\.swf/) >= 0){
	    	this.replacement(request, context, inputStream, offset, count,'ku6.swf')
    		return;
	    }

    	try{
    		this.originalListener.onDataAvailable(request, context, inputStream, offset, count);
    	}catch(err){
    	}
    },

    onStartRequest: function(request, context) {
//    	request.QueryInterface(Ci.nsIHttpChannel);   	
        this.originalListener.onStartRequest(request, context);
    },

    onStopRequest: function(request, context, statusCode) {
//    	ulttool.loginfo('onStopRequest: context is:'+context);
//		httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
//		reqURL = request.URI.spec;
////		ulttool.loginfo('onStopRequest reqURL:'+reqURL);
//		if(reqURL=='http://v.youku.com/crossdomain.xml'){
////			var filename = 'crossdomain.xml';
////	    	filecontent = ulttool.loadfile(filename,null);
////    	  	request.setRequestHeader('Content-Length',''+filecontent.length,true);
//    	  	ulttool.loginfo('Content-Length:'+httpChannel.getResponseHeader('Content-Length'));
//    	}
//    	if(reqURL.search(/http:\/\/static\.youku\.com(\/v[\d\.]*)?\/v\/swf\/player.*\.swf/) >= 0){
//    		var filename = 'player.swf';
//	    	filecontent = ulttool.loadbytefile(filename);
//	    	ulttool.loginfo('Content-Length:'+httpChannel.getResponseHeader('Content-Length'));
////	    	httpChannel.setResponseHeader("Content-Length",filecontent.length,true);
//    	}
        this.originalListener.onStopRequest(request, context, statusCode);
    },

    QueryInterface: function (aIID) {
        if (aIID.equals(Ci.nsIStreamListener) ||
            aIID.equals(Ci.nsISupports)) {
            return this;
        }
        throw Components.results.NS_NOINTERFACE;
    }
}